﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Dracham.Classes
{
    public class FightHandler
    {
        public static FightHandler Instance
        {
            get
            {
                return FightHandlerCreator.Instance;
            }
        }

        public Boolean KnowsSpell(Character c, Spell spell)
        {
            return true;
        }

        public void Handle(DrachamNetwork client)
        {
            String sessionKey = client.ReceiveString(36);
            Int32 attack = client.ReceiveInt32(5);
            String target = client.ReceiveString(36);

            Account acc = GameWorld.Accounts.SingleOrDefault(a => a.SessionKey == sessionKey && a.Client == client);
            if (acc != null)
            {
                Spell sp = GameWorld.SpellPool.SingleOrDefault(s => s.Id == attack);
                if (sp == null) return;

                if (this.KnowsSpell(acc.CurrentCharacter, sp))
                {
                    if (acc.CurrentCharacter.LastAttack.AddSeconds(1).CompareTo(DateTime.Now) <= 0)
                    {
                        acc.CurrentCharacter.LastAttack = DateTime.Now;
                        this.Fight(acc.CurrentCharacter, MobileObject.ResolveObject(target), sp);
                    }
                }
            }
        }

        public void Fight(MobileObject attacker, MobileObject defender, Spell s)
        {
            if (s == null || defender == null || attacker == null) return;

            if (!defender.HasExpired)
            {
                s.Effects.ForEach(delegate(SpellEffect se)
                {
                    try
                    {
                        Int32 curHp = (Int32)defender.GetType().GetProperty("CurrentHitpoints").GetValue(defender, null);
                        Int32 dmg = se.CalculateDamage(attacker);
                        curHp -= dmg;

                        if (curHp <= 0)
                        {
                            if (curHp < 0) curHp = 0;
                            defender.HasExpired = true;
                            defender.Expire();
                        }

                        defender.GetType().GetProperty("CurrentHitpoints").SetValue(defender, curHp, null);

                        if (defender.GetType() == typeof(Character))
                        {
                            Character c = (Character)defender;
                            if (c.Account.Client != null)
                            {
                                    c.Account.Client.Invoke(MessageType.CombatMessage,
                                        new NetworkParameter(defender.GetType().GetProperty("Name").GetValue(defender, null).ToString(), 20),
                                        new NetworkParameter(attacker.GetType().GetProperty("Name").GetValue(attacker, null).ToString(), 20),
                                        new NetworkParameter(dmg.ToString(), 5));
                            }
                        }

                        if (attacker.GetType() == typeof(Character))
                        {
                            Character c = (Character)attacker;
                            if (c.Account.Client != null)
                            {
                                c.Account.Client.Invoke(MessageType.CombatMessage,
                                    new NetworkParameter(defender.GetType().GetProperty("Name").GetValue(defender, null).ToString(), 20),
                                    new NetworkParameter(attacker.GetType().GetProperty("Name").GetValue(attacker, null).ToString(), 20),
                                    new NetworkParameter(dmg.ToString(), 5));
                            }
                        }

                        Console.WriteLine("{0} casts {1} on {2} causing {3} {4} damage",
                            attacker.GetType().GetProperty("Name").GetValue(attacker, null),
                            se.Name,
                            defender.GetType().GetProperty("Name").GetValue(defender, null),
                            dmg,
                            ((EffectType)se.DamageType).ToString());
                    }
                    catch { }
                });
            }
        }
    }

    public static class FightHandlerCreator
    {
        private static readonly FightHandler instance = new FightHandler();

        public static FightHandler Instance
        {
            get
            {
                return instance;
            }
        }
    }
}
